package com.example.travelgd.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.time.ZonedDateTime;
import java.util.Date;
import java.util.UUID;

/**
 * JWT工具类
 */
@Slf4j
public class JwtUtil {
    /**
     * 加密算法
     */
    private static final Algorithm algorithm = Algorithm.HMAC512(JwtConstant.SECRET_KEY);

    /**
     * 功能描述：创建JWT token
     * @return 返回token
     */
    public static String createToken() {
        Date now = new Date();
        String token = JWT.create()
                //下面前7项是JWT PayLoad负载中的官方设置
                .withIssuer(JwtConstant.ISSUER)           // 用于说明该JWT是由谁签发的
                .withSubject(JwtConstant.SUBJECT_SHOP)    // 用于说明该JWT面向的对象
                .withAudience(JwtConstant.SUBJECT_SHOP)   // 用于说明该JWT发送给的用户
                .withExpiresAt(Date.from(ZonedDateTime.now().plusMinutes(JwtConstant.TOKEN_EXPIRE_TIME).toInstant())) // 过期时间
                .withNotBefore(now)                       // 生效时间
                .withIssuedAt(now)                        // 签发时间
                .withJWTId(UUID.randomUUID().toString())  // 说明标明JWT的唯一ID
                .sign(algorithm);

        return token;
    }

    /**
     * 功能描述：解析验证token
     * @param token 加密后的token字符串
     * @return 返回TRUE或FALSE表示token验证成功或失败
     */
    public static Boolean verifyToken(String token) {
        if (StringUtils.isEmpty(token)) {
            return Boolean.FALSE;
        }
        try {
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer(JwtConstant.ISSUER)
                    .withAudience(JwtConstant.SUBJECT_SHOP)
                    .withSubject(JwtConstant.SUBJECT_SHOP)
                    .build();
            verifier.verify(token);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error("Token验证失败：{}", e.getMessage());
            return Boolean.FALSE;
        }
    }

    /**
     * 功能描述：解析token，获取token中包含的用户信息
     * @param token JWT token
     * @return 返回用户名
     * @throws JWTDecodeException JWT解码异常
     */
    public static String getUsernameByToken(String token) throws JWTDecodeException {
        DecodedJWT decodedJWT = JWT.decode(token);
        if (!JwtConstant.SUBJECT_SHOP.equals(decodedJWT.getSubject())) {
            throw new RuntimeException("签名验证失败");
        }
        return decodedJWT.getClaim("username").asString();
    }
}